/*
 * File Name : file_system.cpp
 * Auther : dream.liuguobiao
 * Create Date : 2010-5-7
 * Last Edit : 2010-5-10
 */

#include "file_system.h"
#include "node.h"
#include "directory.h"
#include "file.h"

#include <vector>
#include <iostream>
#include <string>

file_system *file_system::instance_file_system = (file_system*)NULL ;

file_system::file_system()
:root(NULL),current_directory(NULL)
{
this->create_system_tree();
}

file_system *file_system::get_file_system(){
  if( 0 == instance_file_system){
    instance_file_system = new file_system();
  }
  return instance_file_system;
}

node *file_system::get_root(){
 return root;
}

node *file_system::get_current_directory(){
  return current_directory;
}

bool file_system::set_current_directory( node *new_current_directory ){
  current_directory = new_current_directory;
  return true;
}

bool file_system::create_system_tree(){
  std::string tmp_name ( "super_root" );
  node *new_root = new directory();
  new_root->set_name( &tmp_name );
  this->current_directory = new_root;
  this->root = new_root;

  tmp_name = "boot" ;
  node *boot = new directory();
  boot->set_name( &tmp_name );
  this->root->set_son( boot );
  boot->set_father( this->root );

  tmp_name = "bin" ;
  node *bin = new directory();
  bin->set_name( &tmp_name );
  bin->set_father( this->root );
  boot->set_brother( bin );

  tmp_name = "dev" ;
  node *dev = new directory();
  dev->set_name( &tmp_name );
  dev->set_father( this->root );
  bin->set_brother( dev );

  tmp_name = "home" ;
  node *home = new directory();
  home->set_name( &tmp_name );
  home->set_father( this->root );
  dev->set_brother( home );

  tmp_name = "lib" ;
  node *lib = new directory();
  lib->set_name( &tmp_name );
  lib->set_father( this->root );
  home->set_brother( lib );

  tmp_name = "media" ;
  node *media = new directory();
  media->set_name( &tmp_name );
  media->set_father( this->root );
  lib->set_brother( media );

  tmp_name = "mnt" ;
  node *mnt = new directory();
  mnt->set_name( &tmp_name );
  mnt->set_father( this->root );
  media->set_brother( mnt );

  tmp_name = "root" ;
  node *root_son = new directory();
  root_son->set_name( &tmp_name );
  root_son->set_father( this->root );
  root_son->set_mod( 0600 );
  mnt->set_brother( root_son );

  tmp_name = "sbin" ;
  node *sbin = new directory();
  sbin->set_name( &tmp_name );
  sbin->set_father( this->root );
  root_son->set_brother( sbin );

  tmp_name = "srv" ;
  node *srv = new directory();
  srv->set_name( &tmp_name );
  srv->set_father( this->root );
  sbin->set_brother( srv );

  tmp_name = "usr" ;
  node *usr = new directory();
  usr->set_name( &tmp_name );
  usr->set_father( this->root );
  srv->set_brother( usr );

  tmp_name = "var" ;
  node *var = new directory();
  var->set_name( &tmp_name );
  var->set_father( this->root );
  usr->set_brother( var );

  return true;
}

std::vector<node *> *file_system::find_node( node *start_node ,std::string *node_name ){
  find_return.erase( find_return.begin() , find_return.end() );

  this->do_find( node_name , start_node );
  return &find_return ;
}

node *file_system::find_node_just_current_directory( std::string *node_name ){
  node *tmp_node = current_directory->get_son();
  while( NULL != tmp_node ){
    if( *node_name == *(tmp_node->get_name() ) )return tmp_node;
    tmp_node = tmp_node->get_brother();
  }
  return NULL;
}

void file_system::do_find(  std::string *node_name , node *current_node ){
  if(  *node_name == *(current_node->get_name() ) ) {
    find_return.push_back( current_node ) ;
  }
  if( NULL !=  current_node->get_son() ){
    node *tmp_node = current_node->get_son();
    do {
      if( *node_name == *tmp_node->get_name() && 0 != tmp_node->get_type() ) find_return.push_back(tmp_node );
      if( 0 == tmp_node->get_type() ) this->do_find( node_name , tmp_node );
      tmp_node = tmp_node->get_brother();
    } while( NULL != tmp_node );
  }


}

bool file_system::insert_node( node *new_node ) {
  node *tmp_node ;
  if( NULL != current_directory->get_son() ) {
    tmp_node =  current_directory->get_son();
    while( NULL != tmp_node->get_brother() )
      tmp_node = tmp_node->get_brother();
    tmp_node->set_brother( new_node );
    new_node->set_father( tmp_node->get_father() );
  } else {
    tmp_node = current_directory;
    tmp_node->set_son( new_node );
    new_node->set_father( tmp_node );
  }
  return 0 ;
}


int file_system::delete_node ( std::string *node_name ,int current_user_ID ){
  node *tmp_node = current_directory->get_son();
  node *previous_node ;
  while( NULL != tmp_node){
    if( *node_name == *(tmp_node->get_name() ) ){ // found it
      if( NULL != tmp_node->get_son()  ) return 1; //directory not empty
      if( current_user_ID != tmp_node->get_userID() && 0 != current_user_ID )
	return 3;
      if(tmp_node->get_father()->get_son() == tmp_node)
        tmp_node->get_father()->set_son(tmp_node->get_brother() );
      else
        previous_node->set_brother(tmp_node->get_brother() );
      delete tmp_node;
      return 0;
    }else{
    }
    previous_node = tmp_node;
    tmp_node = tmp_node->get_brother();
  }
  return 2; // no this name of node
}
